//延时防抖（在一定时间内只执行最后一次操作）函数需要频繁触发情况时，只有足够空闲的时间，才执行一次
//应用场景：实时搜索（keyup）、拖拽（mousemove）、窗口调整(resize)
export function debounce(callback, delay) {
  let timeout
  return function(...args) {
    clearTimeout(timeout)	//所有频繁的操作都会被清空，只有最后一次的不会清空
    timeout = setTimeout(() => {
		callback.apply(this, args)
    }, delay)
  }
}

/* 使用 */
// 处理函数
// function handle() {
//     console.log(Math.random());
// }
// // 滚动事件
// window.addEventListener('scroll', debounce(handle,500));

//节流:预定一个函数只有在大于等于执行周期时才执行，周期内调用不执行。好像水滴攒到一定重量才会落下。
//应用场景：窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(mousedowm)
// 用时间戳实现
export function throttle(handler, delay) {
    let lastTime = Date.now();
    return function () {
        let nowTime = Date.now();
        if (nowTime - lastTime > delay) {
            handler.apply(this, arguments);
            lastTime = nowTime;
        }
    }
}

//节流用定时器实现代码：
export function throttle(fn,delay) {
    let canRun = true; // 通过闭包保存一个标记
    return function () {
         // 在函数开头判断标记是否为true，不为true则return
        if (!canRun) return;
         // 立即设置为false
        canRun = false;
        // 将外部传入的函数的执行放在setTimeout中
        setTimeout(() => { 
        // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
        // 当定时器没有执行的时候标记永远是false，在开头被return掉
            fn.apply(this, arguments);
            canRun = true;
        }, delay);
    };
}

/* 使用 */
// function sayHi(e) {
//     console.log(e.target.innerWidth, e.target.innerHeight);
// }
// window.addEventListener('resize', throttle(sayHi,500));

//监听DOM样式变化（配置项中attributeFilter只配置了样式）
//应用场景:某个样式需要根据一个dom元素的样式变化而相应改变
export function observerDomRestyle (dom, callback) {	//兼容IE11
  const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
  const observer = new MutationObserver(callback)
  observer.observe(dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true })	//attributeFilter只监听样式style属性的变化
  return observer	//返回observer对象以便使用observer.takeRecords()获取监听列表（清空监听列表）、observer.disconnect()断开监听，详查MutationObserver对象
}